#ifndef RVGSCENE_H
#define RVGSCENE_H

#include <QGraphicsScene>
#include <QUuid>
#include <QList>
#include "common.h"
#include "ShowParam.h"

class Branch;
class Node;
class QAction;
class QMenu;
class Tag;
class GraphicsObject;
class Multipole;

class GraphicsScene : public QGraphicsScene
{
    Q_OBJECT

    QList< Branch* > branches;
    QList< Node* > nodes;

    QPointF mousePressedPos;
    bool showContextMenu;
    QMenu * contextMenu;

    ShowParam * sp;
    std::string rpaFileName;

public:
    typedef QList< Node* >::iterator NodeIterator;
    typedef QList< Branch* >::iterator BranchIterator;

    enum CreationType { ctNone, ctNode, ctBranch, ctTag, ctMultipole };
    void SetCreationType( CreationType ct ) { creationType = ct; }

    QString mdlFile;
    QString GetRpaDir() { return sp->DataPath; }
    void SetRpaDir( QString dir ) { sp->DataPath = dir; }

    Branch * GetBranchByBeginEnd( const int n1, const int n2 );
    Node * GetNodeByID( const int id );
    Node * GetNodeByNum( const int num ) { return nodes.at( num-1 ); }
    int GetNodeNum( int nodeId );
    Node * GetNodeByGUID( QString uid );

    GraphicsObject * GetObjectByUID( QString uid1, QString uid2 = "" );

    std::string GetRpaFile() { return rpaFileName; }
    void SetRpaFile( std::string f ) { rpaFileName = f; }
    void ReadRPA();

    template < class T > QList< T* > getObjectList( bool selected = false )
    {
        QList< T* > ret;
        if( this )
        {
            QList< QGraphicsItem* > list;
            list.clear();
            if( selected )
                list = this->selectedItems();
            else
                list = this->items();

            for( int i=0; i < list.count(); i++  )
            {
                T * t = dynamic_cast< T* >( list.at( i ) );
                if( t )
                    ret.append( t );
            }
        }
        return ret;
    }

private:
    CreationType creationType;

    void createContextMenu( CreationType ct );
    GraphicsObject * getObjectUnderCursor( QPointF & p );
    bool showNodeDialog( Node * n );            // returns true if Dialog accepted
    bool showBranchDialog( Branch * b );        // returns true if Dialog accepted
    bool showTagDialog( Tag * t );              // returns true if Dialog accepted
    bool showMultipoleDialog( Multipole * m );  // returns true if Dialog accepted
    void selectAll();

public:
    explicit GraphicsScene();

    GraphicsObject * GetSelectedObject();

    QList< Branch* > * GetBranches() { return &branches; }
    QList< Node* > * GetNodes() { return &nodes; }
    QList< Tag* > GetTags();

    Branch * AddBranch ( Node * n1, Node * n2, int width = DEFAULT_BRANCH_WIDTH, bool showDialog = true, bool autoColor = true );
    Node * CreateNode( qreal x = 0, qreal y = 0, QUuid uid = QUuid::createUuid(), QColor c = clNodeDef, int size = DEFAULT_NODE_SIZE, bool showDialog = true );
    Tag * CreateTag( GraphicsObject * owner = 0, qreal x = 0, qreal y = 0, QString text = "", bool showDialog = true );
    Multipole * CreateMultipole(  qreal x = 0, qreal y = 0, QUuid uid = QUuid::createUuid(), QColor c = clNodeDef, bool showDialog = false );

    void RmBranchesOfNode( Node * n );
    void ContextMenuClick( QAction * a ) { sltContextMenuClick( a ); }
    void RemoveSelected();
    void SgnUpdateMainVindow() { emit sgnUpdateMainWindow(); }

    void ClearScene();

    ShowParam * GetShowParam() { return sp; }
    void SetShowParam( ShowParam * _sp ) { sp = _sp; }
    void Update();

signals:
    void sgnSaveScheme();

private slots:
    void sltAddBranch( Branch * b );
    void sltRmBranch( Branch * b );
    void sltAddNode( Node * n );
    void sltRmNode( Node * n );
    void sltContextMenuClick( QAction * a );
    void sltAddTag( Tag * t );

protected:
    void mousePressEvent( QGraphicsSceneMouseEvent * e );
    void mouseReleaseEvent( QGraphicsSceneMouseEvent * e );
    void mouseMoveEvent( QGraphicsSceneMouseEvent * e );
    void keyPressEvent( QKeyEvent * e );
    void contextMenuEvent( QGraphicsSceneContextMenuEvent * e );

signals:
    void sgnUpdateMainWindow();
    void sgnUpdateMenuProps();
    void sgnShowQ3D( int nodeId );
    void sgnShowU3D( int nodeId );
    void sgnShowHistogram( int nodeId );

};

#endif // RVGSCENE_H
